import { is, getBusinessObject, isAny } from 'bpmn-js/lib/util/ModelUtil'
import { getTimerEventDefinition, getTimerDefinitionType } from './bpmnPropertyUtils/eventDefinition'
import { useModelerStore } from '@/store/bpmnProcess/modelerStore'

export function getTimerType(element) {
  const businessObject = getBusinessObject(element)
  const timerEventDefinition = getTimerEventDefinition(businessObject)
  return getTimerDefinitionType(timerEventDefinition)
}
export function setTimerType(element, value) {
  const modeling = useModelerStore().getModeling
  const businessObject = getBusinessObject(element)
  const timerEventDefinition = getTimerEventDefinition(businessObject)
  const timerEventDefinitionType = getTimerDefinitionType(timerEventDefinition)
  if (value === timerEventDefinitionType) {
    return
  }
  const formalExpression = createTimerFormalExpression(timerEventDefinition)
  const newProps = {
    timeDuration: undefined,
    timeDate: undefined,
    timeCycle: undefined
  }
  if (value !== '') {
    newProps[value] = formalExpression
  }
  modeling.updateModdleProperties(element, timerEventDefinition, newProps)
}

export function getTimerValue(element, type) {
  const businessObject = getBusinessObject(element)
  const timerEventDefinition = getTimerEventDefinition(businessObject)
  const timerEventFormalExpression = timerEventDefinition.get(type)
  return timerEventFormalExpression && timerEventFormalExpression.get('body')
}
export function setTimerValue(element, type, value) {
  const modeling = useModelerStore().getModeling
  const businessObject = getBusinessObject(element)
  const timerEventDefinition = getTimerEventDefinition(businessObject)
  const timerEventFormalExpression = timerEventDefinition.get(type)
  if (!timerEventFormalExpression) {
    const expression = createTimerFormalExpression(timerEventDefinition)
    expression.set('body', value)
    modeling.updateModdleProperties(element, timerEventDefinition, { [type]: expression })
    return
  }
  modeling.updateModdleProperties(element, timerEventFormalExpression, { body: value })
}

export function getTimerOptions(element) {
  const options = []
  if (isTimerExpressionTypeSupported('timeDate', element)) {
    options.push({
      value: 'timeDate',
      label: '日期'
    })
  }
  if (isTimerExpressionTypeSupported('timeDuration', element)) {
    options.push({
      value: 'timeDuration',
      label: '持续'
    })
  }
  if (isTimerExpressionTypeSupported('timeCycle', element)) {
    options.push({
      value: 'timeCycle',
      label: '循环'
    })
  }
  return options
}

function isTimerExpressionTypeSupported(type, element) {
  const businessObject = getBusinessObject(element)
  switch (type) {
    case 'timeDate':
      return isAny(element, ['bpmn:BoundaryEvent', 'bpmn:IntermediateCatchEvent', 'bpmn:StartEvent'])
    case 'timeCycle':
      if ((is(element, 'bpmn:StartEvent') && !hasParentEventSubProcess(businessObject)) || !isInterrupting(businessObject)) {
        return true
      }
      if (is(element, 'bpmn:BoundaryEvent') && !isInterrupting(businessObject)) {
        return true
      }
      return false
    case 'timeDuration':
      if (isAny(element, ['bpmn:BoundaryEvent', 'bpmn:IntermediateCatchEvent'])) {
        return true
      }
      if (is(element, 'bpmn:StartEvent') && hasParentEventSubProcess(businessObject)) {
        return true
      }
      return false
    default:
      return false
  }
}

function isInterrupting(businessObject) {
  if (is(businessObject, 'bpmn:BoundaryEvent')) {
    return businessObject.get('cancelActivity') !== false
  }
  return businessObject.get('isInterrupting') !== false
}

function hasParentEventSubProcess(businessObject) {
  const parent = businessObject.$parent
  return parent && is(parent, 'bpmn:SubProcess') && parent.get('triggeredByEvent')
}

function createTimerFormalExpression(eventDefinition) {
  const moddle = useModelerStore().getModdle
  const formalExpression = moddle.create('bpmn:FormalExpression', {
    body: undefined
  })
  formalExpression.$parent = eventDefinition
  return formalExpression
}
